home *** CD-ROM | disk | FTP | other *** search
-
- /* Copyright 1986 Eric Jul. May not be used for any purpose without */
- /* written permission from the author. */
- /* The Emerald kernel for the Emerald programming language. */
-
- /* Version 5.2 started 1986-05-21, eric; forked off from kOps.c */
-
- /* This file contains the implementation of the Emerald kernel invoke */
- /* operations as defined in the Kernel Interface Specification. */
-
- #include <stdio.h>
-
- #include "Kernel/h/system.h"
- #include "Kernel/h/assert.h"
- #include "Kernel/h/macros.h"
- #include "Kernel/h/errMsgs.h"
- #include "Kernel/h/mmCodes.h"
- #include "Kernel/h/emTypes.h"
- #include "Kernel/h/timerTypes.h"
- #include "Kernel/h/kmdTypes.h"
- #include "Kernel/h/kEvents.h"
- #include "Kernel/h/emCodes.h"
- #include "Kernel/h/mmMsgTypes.h"
- #include "Kernel/h/lmTypes.h"
- #include "Kernel/h/emkDefs.h"
- #include "Kernel/h/lmCodes.h"
- #include "Kernel/h/hotsTypes.h"
- #include "Kernel/h/map.h"
- #include "Kernel/h/set.h"
- #include "Kernel/h/utils.h"
-
- extern void OTInsert(), schedule();
- extern SSPtr NewProcess(), NewStackSegment(),
- StdStackSegment();
- extern void StartProcessAtAddr(), DiscardStackSegment();
- extern ODP OTLookup();
- extern EmLocation thisNodeLocation;
- extern SSPtr preemptRunning();
- extern CodeAddr FindEntryPointForOp();
- extern MoveMask FindReturnByMoveMask();
- extern void fail(), unavail();
- extern void AddToTTable(), DigestTable(), AddVarToTTable(),
- MoveVarToTTable();
- extern Boolean LoadRequest();
- extern void StartLocate();
- extern void TraverseAndTranslate(), DoTranslate();
- extern void MoveARs(), MoveToTTable();
-
- /* Counters, see measure.c */
- extern int cINVK_InvokeFaults, cINVK_RemoteInvokes;
- extern int cINVK_RemoteReturns, cINVK_RemoteNoSuccessReturns;
- extern int cINVK_RemoteInvokesBytesSent;
- extern int cINVK_RemoteReturnsBytesSent;
- extern int cINVK_RemoteInvokesPacketsSent;
- extern int cINVK_RemoteReturnsPacketsSent;
- extern int cINVK_CallByMovesDone;
- extern int cINVK_CallByMovesBytesSent;
- extern int cINVK_CallByVisitsDone;
- extern int cINVK_CallByVisitsBytesSent;
- extern int cINVK_CallByVisitReturnsDone;
- extern int cINVK_CallByVisitReturnBytesSent;
- extern int cINVK_CallByResultMovesDone;
- extern int cINVK_CallByResultBytesSent;
-
- /* Forward */
- void InvokeReturn();
- HResult InvokeCallBack(), InvokeHandlerCallBack();
- HResult InvokeReplyCallBack();
-
- /************************************************************************/
- /* Invocation */
- /************************************************************************/
-
- /************************************************************************/
- /* Ping-pong message protocol: */
- /* Ping messages can be sent kernel-kernel at anytime. */
- /* The receiving kernel merely responds with a pong message. */
- /* Usefullness: For testing the connection between kernels. */
- /************************************************************************/
-
- int nextPingId = 1;
- int nextLMPingId = 1;
- int vLMPingDataSize = 8;
-
- HResult PingReqHandler(), PongReqHandler();
- void RIPing();
-
- Map InitiallyMap; /* Requests waiting for initially done */
- Map FrozenMap; /* Requests waiting for move or initially */
-
- /************************************************************************/
- /* TryInvoke */
- /************************************************************************/
- void TryInvoke(fOpNumber, fAbConPtr, fCalleeGODP, fCallerSSP)
- int fOpNumber; /* operation number */
- AbConPtr fAbConPtr; /* AbConVector ptr */
- GODP fCalleeGODP; /* target */
- SSPtr fCallerSSP; /* caller */
- /* Attempt to do an invocation, checking for all the possible conditions*/
- {
- SSAddr returnAddr;
- register SSPtr callerSSP = fCallerSSP;
-
- if (fCalleeGODP->tag.isResident && (!fCalleeGODP->tag.setUpDone)) {
- register InitiallyReqPtr p;
- Map theMap;
- KMDTrace("Invoke", 3, "%s blocking on invoke of %s\n",
- PPPOID(callerSSP->processOID), PPGOID(fCalleeGODP->ownOID));
- KMDTrace("Invoke", 3, "Initially not done yet; blocking in %s\n",
- PPSSPlace(callerSSP));
- p = mNewRequest(Initially);
- p->calleeGODP = fCalleeGODP;
- p->theProcess = callerSSP;
- p->opNumber = fOpNumber;
- p->theAbConPtr = fAbConPtr;
- callerSSP->invokePtr = (GenericPtr) p;
- callerSSP->status.rs = SSInitiallyWait;
- KMDTrace("LineNumber", 4, "%s waiting for initially done in %s\n",
- PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
- theMap = (Map) Map_Lookup(InitiallyMap, (int) fCalleeGODP);
- if (IsNIL(theMap)) {
- theMap = Map_Create();
- KMDTrace("Invoke", 4, "Creating initially map for GODP 0x%05x\n",
- fCalleeGODP);
- Map_Insert(InitiallyMap, (int) fCalleeGODP, (int) theMap);
- KMDTrace("FixMe", 5, "Ought to use Set or Bag\n");
- }
- Map_Insert(theMap, (int) p, NULL);
- return;
- }
-
- KMDTrace("Invoke", 3, "%s resident invoke of %s op #%d\n",
- PPPOID(callerSSP->processOID), PPGOID(fCalleeGODP->ownOID),
- fOpNumber);
-
- /* Prepare the stack */
-
- POPIT(callerSSP->regs.sp, returnAddr);
- PUSHIT(callerSSP->regs.sp, callerSSP->regs.l);
- PUSHIT(callerSSP->regs.sp, callerSSP->regs.g);
- PUSHIT(callerSSP->regs.sp, callerSSP->regs.b);
- callerSSP->regs.l = (SSAddr) callerSSP->regs.sp;
- PUSHIT(callerSSP->regs.sp, returnAddr);
- PUSHIT(callerSSP->regs.sp, fAbConPtr->opVector[fOpNumber].opAddress);
- callerSSP->regs.b = fCalleeGODP;
- callerSSP->regs.g = fCalleeGODP->dataPtr;
- KMDTrace("Invoke", 3, "%s unblocked in %s\n",
- PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
- schedule(callerSSP);
- }
-
- /************************************************************************/
- /* Invocation (trap on frozen) */
- /************************************************************************/
-
-
- void Invoke(fOpNumber, fAbConPtr, fCalleeGODP)
- AbConPtr fAbConPtr; /* AbConVector ptr */
- int fOpNumber; /* operation number */
- GODP fCalleeGODP; /* target */
- /* The call should probably be renamed FrozenTrap since there can
- be the following reasons for it:
- 1. Remote invocation (handled here).
- 2. Invoke of object when initially has not been done yet.
- 3. Garbage Collection trap. (Not impl yet)
- */
- {
- register InvokeReqPtr req;
- register AbConOpVectorEntryPtr entryPtr;
- register SSPtr callerSSP;
- NodeNum nodeLNN;
- Map theMap;
- #ifdef DONEBYSTUB
- CodeAddr returnAddr;
- DynamicLinkPtr dynLink;
- #endif DONEBYSTUB
-
- if (IsNIL(fCalleeGODP)) {
- KMDTrace("LineNumber", 2, "Invoke of NIL\n");
- ErrMsg("Invoke of NIL somewhere -- kernel cannot recover -- sorry\n");
- abort();
- }
-
- callerSSP = preemptRunning();
- callerSSP->status.rs = SSInvokeWait; /* assumed for now */
- KMDTrace("LineNumber", 4, "%s invoke via kernel in %s\n",
- PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
-
- #ifdef DONEBYSTUB
- /* Remove dynamic link from stack and set return addr */
- dynLink = (DynamicLinkPtr) (callerSSP->regs.sp);
- returnAddr = dynLink->ip;
- callerSSP->regs.b = dynLink->b;
- callerSSP->regs.sp = (SSAddr) (dynLink+1);
- PUSHIT(callerSSP->regs.sp, returnAddr);
- #endif DONEBYSTUB
-
- KMDTrace("Invoke", 3, "%s invoking %s op #%d at %s\n",
- PPPOID(callerSSP->processOID), PPGOID(fCalleeGODP->ownOID), fOpNumber,
- PPSSPlace(callerSSP));
-
- /*
- * cINVK_InvokeFaults counts how many times processes fault to this
- * procedure.
- */
- cINVK_InvokeFaults++;
-
- if (fCalleeGODP->tag.isResident && (!fCalleeGODP->tag.setUpDone)) {
- register InitiallyReqPtr p;
- KMDTrace("Invoke", 3, "%s blocking on invoke of %s\n",
- PPPOID(callerSSP->processOID), PPGOID(fCalleeGODP->ownOID));
- KMDTrace("Invoke", 3, "Initially for not done yet; blocking in %s\n",
- PPSSPlace(callerSSP));
- KMDTrace("LineNumber", 4, "%s waiting for initially done in %s\n",
- PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
- p = mNewRequest(Initially);
- p->calleeGODP = fCalleeGODP;
- p->theProcess = callerSSP;
- p->opNumber = fOpNumber;
- p->theAbConPtr = fAbConPtr;
- callerSSP->invokePtr = (GenericPtr) p;
- callerSSP->status.rs = SSInitiallyWait;
- KMDTrace("LineNumber", 4, "%s waiting for initially done in %s\n",
- PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
- theMap = (Map) Map_Lookup(InitiallyMap, (int) fCalleeGODP);
- if (IsNIL(theMap)) {
- theMap = Map_Create();
- KMDTrace("Invoke", 4, "Creating initially map for 0x%05x\n",
- fCalleeGODP);
- Map_Insert(InitiallyMap, (int) fCalleeGODP, (int) theMap);
- KMDTrace("FixMe", 5, "Ought to use Set for theMap\n");
- }
- Map_Insert(theMap, (int) p, NULL);
- return;
- }
-
- if (fCalleeGODP->tag.isResident) {
- ErrMsg("Found object frozen in %s\n", PPSSPlace(callerSSP));
- fail(callerSSP);
- return;
- }
-
-
- if (IsNULL(fCalleeGODP->ownOID)) {
- OTInsert((ODP) fCalleeGODP);
- }
-
- /* Build the InvokeRequest and wait for the invocation to return */
- req = mNewRequest(Invoke);
- req->requestor = callerSSP;
- req->targetGODP = fCalleeGODP;
- req->theAbConPtr = fAbConPtr;
-
- /* Put the request reference into stack segment descriptor */
- callerSSP->invokePtr = (GenericPtr) req;
-
- if (IsNULL(callerSSP->ownOID)) {
- OTInsert((ODP) callerSSP->ownSSODP);
- callerSSP->ownOID = callerSSP->ownSSODP->ownOID;
- }
-
- req->i.hdr.itemTag = InvokeITag;
- req->i.hdr.size = sizeof (req->i);
- req->i.callerSSOID = callerSSP->ownOID;
- req->i.callerLoc = thisNodeLocation;
- req->i.processOID = callerSSP->processOID;
- req->i.targetOID = fCalleeGODP->ownOID;
- req->i.targetTryAtLoc = fCalleeGODP->ownLoc;
- req->i.abConTag = fAbConPtr->tag;
- req->i.abstractTypeOID = fAbConPtr->ATOID;
- req->i.concreteTypeOID = fAbConPtr->CodeOID;
- req->i.stackAvailable = callerSSP->availStack +
- byteOffset(callerSSP->splimit, callerSSP->regs.sp);
- entryPtr = &fAbConPtr->opVector[fOpNumber];
- req->i.opOID = entryPtr->operationNameOID;
- req->i.opNumber = fOpNumber;
- req->i.argumentCount = entryPtr->argumentCount;
- req->i.resultCount = entryPtr->resultCount;
- req->i.resultMoveMask = 0;
- req->i.paramMoveMask = 0;
-
- KMDTrace("Invoke", 5, "Op #%d, OpOID 0x%08x, %d arg%s, %d result%s\n",
- fOpNumber, req->i.opOID, req->i.argumentCount,
- mPLURAL(req->i.argumentCount), req->i.resultCount,
- mPLURAL(req->i.resultCount));
-
- /* Fire up the location protocol, if necessary */
- nodeLNN = mGetLocNodeNum(fCalleeGODP->ownLoc);
- if (nodeLNN == NULL) {
- KMDTrace("Invoke", 3, "Firing up location protocol\n");
- req->status = IRLocatingTarget;
- req->hdr.callBack = (GenericHandlerPtr) InvokeCallBack;
- StartLocate((GenericReqPtr) req, (ODP) fCalleeGODP);
- return;
- }
- InvokeCallBack(req, fCalleeGODP->ownOID);
- }
-
- void InvokeWithMove(fOpNumber, fAbConPtr, fCalleeGODP)
- AbConPtr fAbConPtr; /* AbConVector ptr */
- int fOpNumber; /* operation number */
- GODP fCalleeGODP; /* target */
- /* The call should probably be renamed FrozenTrap since there can
- be the following reasons for it:
- 1. Remote invocation (handled here).
- 2. Invoke of object when initially has not been done yet.
- 3. Garbage Collection trap. (Not impl yet)
- */
- {
- register InvokeReqPtr req;
- register AbConOpVectorEntryPtr entryPtr;
- register SSPtr callerSSP;
- MoveMask theMoveMask, theVisitMask;
- NodeNum nodeLNN;
- Map theMap;
-
- /*
- * cINVK_InvokeFaults counts how many times processes fault to this
- * procedure.
- */
- cINVK_InvokeFaults++;
-
- callerSSP = preemptRunning();
- callerSSP->status.rs = SSInvokeWait; /* assumed for now */
- /* Fetch masks from stack */
- POPIT(callerSSP->regs.sp, theMoveMask);
- POPIT(callerSSP->regs.sp, theVisitMask);
-
- if (IsNIL(fCalleeGODP)) {
- KMDTrace("LineNumber", 2, "Invoke of NIL\n");
- ErrMsg("Invoke of NIL somewhere -- kernel cannot recover -- sorry\n");
- abort();
- }
-
- KMDTrace("LineNumber", 4, "%s invoke via kernel in %s\n",
- PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
-
- #ifdef DONEBYSTUB
-
- CodeAddr returnAddr;
- DynamicLinkPtr dynLink;
-
- /* This stuff is obsolete */
- /* Remove dynamic link from stack and set return addr */
- dynLink = (DynamicLinkPtr) (callerSSP->regs.sp);
- returnAddr = dynLink->ip;
- callerSSP->regs.b = dynLink->b;
- callerSSP->regs.sp = (SSAddr) (dynLink+1);
- PUSHIT(callerSSP->regs.sp, returnAddr);
- #endif DONEBYSTUB
-
- KMDTrace("Invoke", 3,
- "%s invoking %s with move/visit params op #%d at %s\n",
- PPPOID(callerSSP->processOID), PPGOID(fCalleeGODP->ownOID), fOpNumber,
- PPSSPlace(callerSSP));
-
- KMDTrace("Invoke", 4, "Move Mask 0x%02x Visit Mask 0x%02x\n",
- theMoveMask, theVisitMask);
- if (fCalleeGODP->tag.isResident && (!fCalleeGODP->tag.setUpDone)) {
- register InitiallyReqPtr p;
- KMDTrace("Invoke", 3, "%s blocking on invoke of %s\n",
- PPPOID(callerSSP->processOID), PPGOID(fCalleeGODP->ownOID));
- KMDTrace("Invoke", 3, "Initially for not done yet; blocking in %s\n",
- PPSSPlace(callerSSP));
- KMDTrace("LineNumber", 4, "%s waiting for initially done in %s\n",
- PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
- p = mNewRequest(Initially);
- p->calleeGODP = fCalleeGODP;
- p->theProcess = callerSSP;
- p->opNumber = fOpNumber;
- p->theAbConPtr = fAbConPtr;
- callerSSP->invokePtr = (GenericPtr) p;
- callerSSP->status.rs = SSInitiallyWait;
- KMDTrace("LineNumber", 4, "%s waiting for initially done in %s\n",
- PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
- theMap = (Map) Map_Lookup(InitiallyMap, (int) fCalleeGODP);
- if (IsNIL(theMap)) {
- theMap = Map_Create();
- KMDTrace("Invoke", 4, "Creating initially map for 0x%05x\n",
- fCalleeGODP);
- Map_Insert(InitiallyMap, (int) fCalleeGODP, (int) theMap);
- KMDTrace("FixMe", 5, "Ought to use Set for theMap\n");
- }
- Map_Insert(theMap, (int) p, NULL);
- return;
- }
-
- if (fCalleeGODP->tag.isResident) {
- ErrMsg("Found object frozen in %s\n", PPSSPlace(callerSSP));
- fail(callerSSP);
- return;
- }
- if (IsNULL(fCalleeGODP->ownOID)) {
- OTInsert((ODP) fCalleeGODP);
- }
-
- /* Build the InvokeRequest and wait for the invocation to return */
- req = mNewRequest(Invoke);
- req->requestor = callerSSP;
- req->targetGODP = fCalleeGODP;
- req->theAbConPtr = fAbConPtr;
-
- /* Put the request reference into stack segment descriptor */
- callerSSP->invokePtr = (GenericPtr) req;
-
- if (IsNULL(callerSSP->ownOID)) {
- OTInsert((ODP) callerSSP->ownSSODP);
- callerSSP->ownOID = callerSSP->ownSSODP->ownOID;
- }
-
- req->i.hdr.itemTag = InvokeITag;
- req->i.hdr.size = sizeof (req->i);
- req->i.callerSSOID = callerSSP->ownOID;
- req->i.callerLoc = thisNodeLocation;
- req->i.processOID = callerSSP->processOID;
- req->i.targetOID = fCalleeGODP->ownOID;
- req->i.targetTryAtLoc = fCalleeGODP->ownLoc;
- req->i.abConTag = fAbConPtr->tag;
- req->i.abstractTypeOID = fAbConPtr->ATOID;
- req->i.concreteTypeOID = fAbConPtr->CodeOID;
- req->i.stackAvailable = callerSSP->availStack +
- byteOffset(callerSSP->splimit, callerSSP->regs.sp);
- entryPtr = &fAbConPtr->opVector[fOpNumber];
- req->i.opOID = entryPtr->operationNameOID;
- req->i.opNumber = fOpNumber;
- req->i.argumentCount = entryPtr->argumentCount;
- req->i.resultCount = entryPtr->resultCount;
- req->i.resultMoveMask = theVisitMask;
- req->i.paramMoveMask = theMoveMask;
-
- KMDTrace("Invoke", 4, "Op #%d, OpOID 0x%08x, %d arg%s, %d result%s\n",
- fOpNumber, req->i.opOID, req->i.argumentCount,
- mPLURAL(req->i.argumentCount), req->i.resultCount,
- mPLURAL(req->i.resultCount));
-
- /* Fire up the location protocol, if necessary */
- nodeLNN = mGetLocNodeNum(fCalleeGODP->ownLoc);
- if (nodeLNN == NULL) {
- KMDTrace("Invoke", 3, "Firing up location protocol\n");
- req->status = IRLocatingTarget;
- req->hdr.callBack = (GenericHandlerPtr) InvokeCallBack;
- StartLocate((GenericReqPtr) req, (ODP) fCalleeGODP);
- return;
- }
- InvokeCallBack(req, fCalleeGODP->ownOID);
- }
-
- /*ARGSUSED*/
- HResult InvokeCallBack(fReq, fOID)
- InvokeReqPtr fReq;
- OID fOID;
- /* Call back is done when object has been located */
- {
- register InvokeReqPtr req;
- register int i;
- register AVariablePtr paramAddr;
- register SSPtr callerSSP;
- NodeNum nodeLNN;
- LMHandle myHandle;
- int paramSize, opNumber;
- ParamItem myParamItem;
- Map m;
- Set ar;
- KKStatus kstat;
- GODP targetGODP;
- AbConPtr targetAbCon;
-
- req = fReq;
- callerSSP = req->requestor;
- targetGODP = req->targetGODP;
- targetAbCon = req->theAbConPtr;
- nodeLNN = mGetLocNodeNum(targetGODP->ownLoc);
-
- KMDTrace("Invoke", 4, "%s ready to invoke %s at node #%d\n",
- PPPOID(callerSSP->processOID), PPGOID(targetGODP->ownOID), nodeLNN);
-
- if (nodeLNN == GetLNN()) {
- /* It is here so just do a resident invoke */
- KMDTrace("Invoke", 3, "InvokeCallBack found %s resident\n",
- PPGOID(targetGODP->ownOID));
- opNumber = req->i.opNumber;
- FreeRequest((GenericReqPtr) req);
- callerSSP->invokePtr = (GenericPtr) NULL;
- TryInvoke(opNumber, targetAbCon, targetGODP, callerSSP);
- return;
- }
-
- /* Build invocation message request */
- LMStartMsg(&myHandle, KMSG_EmKernel, EMKM_InvokeReq, nodeLNN);
- LMPutData(&myHandle, &req->i, sizeof(req->i));
-
- /* Start on the translation map */
- m = Map_Create();
- ar = Set_Create();
-
- /* Put the stack segment into the translation table */
-
- /* Copy the arguments */
- if (req->i.argumentCount > 0) {
- int pos;
-
- assert(req->i.argumentCount <= 32);
- paramSize = req->i.argumentCount * sizeof(AVariable);
- myParamItem.hdr.itemTag = ParamTag;
- myParamItem.hdr.size = paramSize + sizeof(ItemHdr);
- paramAddr = (AVariablePtr)
- addOffset(callerSSP->regs.sp, sizeof(CodeAddr));
- LMPutData(&myHandle, &myParamItem, sizeof(ItemHdr));
- LMPutData(&myHandle, paramAddr, paramSize);
-
- /* Traverse parameter area and send translation info */
- for (i = req->i.argumentCount; i ; i--, paramAddr++) {
- if ((req->i.paramMoveMask >> (i-1)) & 0x1) {
- KMDTrace("Invoke", 4, "Param #%d by move %s\n", i,
- PPVar(paramAddr));
- cINVK_CallByMovesDone++;
- pos = LMCurrentPosition(&myHandle);
- MoveVarToTTable(&myHandle, paramAddr, m, ar);
- cINVK_CallByMovesBytesSent +=
- (LMCurrentPosition(&myHandle) - pos);
- } else if ((req->i.resultMoveMask >> (i-1)) & 0x1) {
- KMDTrace("Invoke", 4, "Param #%d by visit %s\n", i,
- PPVar(paramAddr));
- cINVK_CallByVisitsDone++;
- pos = LMCurrentPosition(&myHandle);
- MoveVarToTTable(&myHandle, paramAddr, m, ar);
- cINVK_CallByVisitsBytesSent +=
- (LMCurrentPosition(&myHandle) - pos);
- } else {
- KMDTrace("Invoke", 4, "Param #%d by ref %s\n", i,
- PPVar(paramAddr));
- AddVarToTTable(&myHandle, paramAddr, m, ar);
- }
- }
- }
-
- /* Put the current stack segment into the translation table */
- AddToTTable(&myHandle, (ODP) callerSSP->ownSSODP, m, ar);
-
- MoveARs(&myHandle, m, ar);
-
- /*
- * cINVK_RemoteInvokes counts the number of times that we think that we
- * need to do a remote invoke.
- */
- cINVK_RemoteInvokes++;
- cINVK_RemoteInvokesBytesSent += LMCurrentPosition(&myHandle);
- cINVK_RemoteInvokesPacketsSent += LMPacketPosition(&myHandle);
-
- /* Ship the message */
- kstat = LMSendMsg(&myHandle);
-
- req->status = IRWaitingForInvokeReply;
-
- /* Clean up */
- Map_Destroy(m);
- Set_Destroy(ar);
-
-
- /* Finally, check that we could send the msg */
-
- if (!mSUCCESS(kstat)) {
- KMDTrace("Invoke", 2, "%s target object %s unavailable in %s\n",
- PPPOID(callerSSP->processOID), PPGOID(targetGODP->ownOID),
- PPSSPlace(callerSSP));
- FreeRequest((GenericReqPtr) callerSSP->invokePtr);
- callerSSP->invokePtr = (GenericPtr) NULL;
- unavail(callerSSP, targetGODP, targetAbCon);
- return;
- }
- }
-
- /************************************************************************/
- /* Invocation message arrival */
- /************************************************************************/
-
- HResult InvokeHandler(fHandle)
- LMHandle fHandle;
- /* Handles incoming invocation messages */
- {
- register SSPtr newSS;
- register IncomingIReqPtr req;
- register int i;
- NodeNum srcNode;
- int length, argumentSize;
- SSODP callerSSODP;
- ParamItem myParamItem;
- OID theCTOID;
- ODP theOldODP;
-
- srcNode = fHandle->mmMsgHdr.MsgSrc;
- KMDTrace("Invoke", 3, "*** Invocation Message from %d ***\n", srcNode);
-
- /* Build incoming invocation request */
- req = mNewRequest(IncomingI);
-
- req->visitorSet = (Set) NULL;
-
- /* Get the request */
- length = sizeof(req->i);
- LMGetData(&fHandle, &req->i, &length);
- assert(length == sizeof(req->i));
- KMDTrace("Invoke", 3, "Caller SSOID 0x%05x target %s opOID #0x%08x\n",
- req->i.callerSSOID, PPGOID(req->i.targetOID), req->i.opOID);
- KMDTrace("Invoke", 4, "ATOID \t0x%05x\tstackAvail %5d\n",
- req->i.abstractTypeOID, req->i.stackAvailable);
- KMDTrace("Invoke", 4, "%d %s, %d %s\n", req->i.argumentCount,
- req->i.argumentCount == 1 ? "argument" : "arguments",
- req->i.resultCount, req->i.resultCount == 1 ? "result" : "results");
- KMDTrace("Invoke", 4, "MoveMask 0x%01x VisitMask 0x%01x\n",
- req->i.paramMoveMask, req->i.resultMoveMask);
- KMDTrace("FixMe", 5,
- "(Fix me: should update target location before lookup - re move)\n");
-
- /* Lookup target */
- req->targetGODP = (GODP) OTLookup(req->i.targetOID);
-
- /* HACK: delay processing of invoke request if the object has not
- been set up properly in the hope that it will be later */
- if (NonNULL(req->targetGODP) && (!req->targetGODP->tag.setUpDone)) {
- KMDTrace("Invoke", 2, "HACK: delay processing of Invoke for 0x%06x\n",
- req->targetGODP);
- }
-
- /* Allocate a new SS to handle the request */
- newSS = req->theProcess = StdStackSegment();
- newSS->processOID = req->i.processOID;
- newSS->availStack = req->i.stackAvailable - newSS->segmentSize;
- newSS->rPtr = (int *) req;
-
- callerSSODP = (SSODP) OTLookup(req->i.callerSSOID);
- if (IsNULL(callerSSODP)) {
- /* Have not heard from this SS before */
- KMDTrace("Invoke", 4,
- "First time we have heard from SSOID 0x%08.8x\n",
- req->i.callerSSOID);
- /* Note, it will be inserted by Digest table */
- }
-
- /* Make room on stack for results */
- if (req->i.resultCount > 0) {
- for (i = req->i.resultCount; i > 0; i--) {
- PUSHIT(newSS->regs.sp, EMNIL);
- PUSHIT(newSS->regs.sp, EMNIL);
- }
- KMDTrace("Invoke", 4,
- "Allocating room for %d result%s; new sp 0x%05x\n",
- req->i.resultCount, mPLURAL(req->i.resultCount), newSS->regs.sp);
- }
- /* Copy parameters onto stack */
-
- if (req->i.argumentCount > 0) {
- length = sizeof(ItemHdr);
- LMGetData(&fHandle, &myParamItem, &length);
- assert(length == sizeof(ItemHdr));
- assert(myParamItem.hdr.itemTag == ParamTag);
- argumentSize = myParamItem.hdr.size - length;
- assert(argumentSize == req->i.argumentCount * sizeof(AVariable));
- /* Allocate room for arguments on stack */
- req->paramAddr = (AVariablePtr) (newSS->regs.sp = (SSAddr)
- addOffset(newSS->regs.sp, -argumentSize) );
- KMDTrace("Invoke", 4, "argument size %d, new sp: 0x%05x\n",
- argumentSize, newSS->regs.sp);
- /* Copy parameters to stack */
- length = argumentSize;
- LMGetData(&fHandle, newSS->regs.sp, &length);
- KMDTrace("Invoke", 5,
- "want argument size %d, got %d\n", argumentSize, length);
- assert(length == argumentSize);
- }
-
- /* Create translation map */
- req->m = Map_Create();
- req->neededMap = Map_Create();
- req->newSet = Set_Create();
-
- /* Digest translation table information */
- DigestTable(&fHandle, req->m, req->neededMap, req->newSet, 0);
-
- LMClose(&fHandle);
-
- req->status = IHLoadingCode;
-
- if (Map_Count(req->neededMap) > 0) {
- Boolean didit;
- Map gotLoaded; /* Holds the ones loaded now */
- CodeODP newODP;
-
- gotLoaded = Map_Create();
- /* Have to load some code */
-
- Map_For(req->neededMap, theCTOID, theOldODP)
- didit = LoadRequest(theCTOID, (GenericReqPtr) req);
- if (didit) Map_Insert(gotLoaded, (int) theCTOID, (int) theOldODP);
- Map_Next
-
- Map_For(gotLoaded, theCTOID, theOldODP)
- /* Delete it since no call back will occur */
- Map_Delete(req->neededMap, (int) theCTOID);
- newODP = (CodeODP) OTLookup(theCTOID);
- assert(NonNULL(newODP));
- Map_Insert(req->m, (int) theOldODP, (int) newODP->dataPtr);
- Map_Next
-
- Map_Destroy(gotLoaded);
-
- if (Map_Count(req->neededMap) > 0) return;
- }
-
- req->status = IHCodeLoadDone;
- InvokeHandlerCallBack((GenericReqPtr) req, (OID) NULL);
- return;
- }
-
- /**********************************************************************/
- /* InvokeHandlerCallBack */
- /**********************************************************************/
- HResult InvokeHandlerCallBack(fReq, fOID)
- GenericReqPtr fReq;
- OID fOID;
- {
- register IncomingIReqPtr req;
- register AVariablePtr p;
- register SSPtr newSS;
- CodeAddr theEntryPoint;
-
- req = (IncomingIReqPtr) fReq;
- newSS = req->theProcess;
-
- KMDTrace("Invoke", 4, "InvokeHandlerCallBack; OID %s status %s\n",
- PPOID(fOID),
- req->status == IHLoadingCode ? "Loading Code" :
- req->status == IHCodeLoadDone? "Code load done" :
- req->status == IHObjectNonFrozen ? "Object Not Frozen" :
- "BAD STATUS");
-
- switch (req->status) {
-
- case IHLoadingCode: {
- ODP oldODP;
- CodeODP newODP;
-
- /* Requested code has arrived */
- oldODP = (ODP) Map_Lookup(req->neededMap, (int) fOID);
- if (IsNIL(oldODP)) {
- ErrMsg("InvokeHandlerCallBack %s -- ignored\n");
- return;
- }
- Map_Delete(req->neededMap, (int) fOID);
-
- newODP = (CodeODP) OTLookup(fOID);
- assert(NonNULL(newODP));
- /* (Note, m uses the pointer to the code area.) */
- Map_Insert(req->m, (int) oldODP, (int) newODP->dataPtr);
- KMDTrace("Invoke", 5, "%s loaded, (0x%04x -> 0x%04x)\n", PPCOID(fOID),
- oldODP, newODP->dataPtr);
-
- /* Check for completion of code loads */
- if (Map_Count(req->neededMap) == 0) {
- KMDTrace("Invoke", 3, "All needed code loaded\n");
- req->status = IHCodeLoadDone;
- InvokeHandlerCallBack((GenericReqPtr) req, (OID) NULL);
- }
- break;
- }
-
- case IHCodeLoadDone: {
- register int i;
- ODP aVisitorODP;
-
- /* All needed code has been loaded, now translate */
- DoTranslate(req->newSet, req->m, 0);
-
- if (req->i.argumentCount > 0) {
- /* Translate parameters */
- p = req->paramAddr;
- for (i = req->i.argumentCount; i; p++, i--) {
- if (p->myAbConPtr == (AbConPtr) EMNIL) {
- KMDTrace("Invoke", 4, "Param #%d is NIL\n", i);
- } else {
- p->myAbConPtr =
- (AbConPtr) Map_Lookup(req->m, (int) p->myAbConPtr);
- assert(p->myAbConPtr != (AbConPtr) EMNIL);
- KMDTrace("Invoke", 4, "new AbConPtr 0x%05x\n",
- p->myAbConPtr);
- if(p->myAbConPtr->tag.hasNoPointer) {
- KMDTrace("Invoke", 4,
- "Param %d integer (or such) = %d, oldAB 0x%05x\n",
- i, p->myAddr, p->myAbConPtr);
- } else if (p->myAddr == (DataAddr) EMNIL) {
- KMDTrace("Invoke", 4,
- "Param #%d is NIL (with non-NIL AbCon)\n", i,
- p->myAddr);
- } else {
- KMDTrace("Invoke", 4,
- "Param #%d OldODP 0x%05x new AbConPtr 0x%05x\n",
- i, p->myAddr, p->myAbConPtr);
- /* Translate ODP */
- p->myAddr =
- (DataAddr) Map_Lookup(req->m, (int) p->myAddr);
- assert(p->myAddr != (DataAddr) EMNIL);
- aVisitorODP = (ODP) p->myAddr;
- if (aVisitorODP->G.tag.global &&
- ((req->i.resultMoveMask >> (i-1)) & 0x1)
- ) {
- KMDTrace("Move", 3, "Call-by-visit OID %s\n",
- PPGOID(aVisitorODP->G.ownOID));
- if (IsNULL(req->visitorSet)) {
- KMDTrace("Move", 5,
- "Allocating visitor set\n");
- req->visitorSet = Set_Create();
- }
- Set_Insert(req->visitorSet,
- (int) aVisitorODP->G.ownOID);
- }
- }
- }
- KMDTrace("Invoke", 5, "After translate: (0x%05x, 0x%05x)\n",
- p->myAbConPtr,p->myAddr);
- }
- }
-
- /* Cleanup */
- Map_Destroy(req->m);
- Map_Destroy(req->neededMap);
- Set_Destroy(req->newSet);
-
- if (IsNULL(req->targetGODP) || (!req->targetGODP->tag.isResident)) {
- InvokeReturn(newSS, INVOKEUNAVAILABLE);
- DiscardStackSegment(newSS);
- return;
- }
-
- /* Check to see if there is enough stack left */
- if (req->i.stackAvailable < newSS->segmentSize) {
- KMDTrace("Invoke", 2, "%s too low on stack space; only %d left\n",
- PPPOID(req->i.processOID), req->i.stackAvailable);
- InvokeReturn(newSS, INVOKEFAILED);
- DiscardStackSegment(newSS);
- return;
- }
-
- if (req->targetGODP->tag.frozen) {
- Set reqSet;
-
- KMDTrace("Invoke", 3, "Invoke: OD frozen ODTag: %s\n",
- PPODTag(req->targetGODP->tag));
- if (req->targetGODP->tag.setUpDone) {
- ErrMsg("Cannot handle frozen remote object ODTag %s\n",
- PPODTag(req->targetGODP->tag));
- abort();
- }
- req->status = IHCodeLoadDone;
- reqSet = (Set)
- Map_Lookup(FrozenMap, (int) req->targetGODP->ownOID);
- if (IsNIL(reqSet)) {
- reqSet = Set_Create();
- Map_Insert(FrozenMap, (int) req->targetGODP->ownOID,
- (int) reqSet);
- KMDTrace("Invoke", 5, "Creating frozen set for %s\n",
- PPGOID(req->targetGODP->ownOID));
- }
- KMDTrace("Invoke", 3,
- "Inserting 0x%06x process %s into frozen set\n", req,
- PPPOID(req->theProcess->processOID));
- Set_Insert(reqSet, (int) req);
- return;
- }
- /* Fall through !! */
- }
-
- case IHObjectNonFrozen: {
- register CodePtr theCodePtr;
- theCodePtr = req->targetGODP->dataPtr->myCodePtr;
- theEntryPoint = FindEntryPointForOp(theCodePtr, req->i.opOID);
- if (req->i.resultCount > 0) {
- req->returnByMoveMask = FindReturnByMoveMask(theCodePtr,
- theEntryPoint);
- } else {
- req->returnByMoveMask = 0;
- }
-
- StartProcessAtAddr(req->theProcess, req->targetGODP,
- req->targetGODP->dataPtr, theEntryPoint);
- break;
- }
-
- default: {
- ErrMsg("Bad move status %d in InvokeHandlerCallBack\n", req->status);
- abort();
- }
- }
- }
-
- /************************************************************************/
- /* Invocation reply generation */
- /************************************************************************/
-
- /* NOT a kernel call -- called from Return off stack or upon failure */
- void InvokeReturn(fSSPtr, fResult)
- register SSPtr fSSPtr;
- InvokeResult fResult;
- /* Reply to an invocation */
- {
- register IncomingIReqPtr req;
- register SSODP callerSSODP;
- register int i;
- register AVariablePtr paramAddr;
- InvokeReplyItem replyItem;
- LMHandle replyHandle;
- int paramSize;
- ParamItem myParamItem;
- Map m; /* ODPs sent */
- Set ar; /* ARs to send */
- GODP visitingGODP;
- OID visitingOID;
-
- req = (IncomingIReqPtr) fSSPtr->rPtr;
- callerSSODP = (SSODP) OTLookup(req->i.callerSSOID);
- assert(NonNULL(callerSSODP));
- KMDTrace("Invoke", 3, "%s replying to SSOID 0x%05x @ %s, result %s\n",
- PPPOID(fSSPtr->processOID), callerSSODP->ownOID,
- PPLoc(callerSSODP->ownLoc), PPInvokeResult(fResult));
-
- if (callerSSODP->tag.isResident) {
- register SSPtr callerSSP;
- register InvokeReqPtr invokeReq;
-
- KMDTrace("Invoke", 3, "Performing local return after remote call\n");
- /* much code copied from InvokeReplyHandler */
-
- /* Find the original req */
- callerSSP = callerSSODP->dataPtr;
- invokeReq = (InvokeReqPtr) callerSSP->invokePtr;
- assert(NonNULL(invokeReq));
-
- switch (fResult) {
-
- case INVOKEFAILED: {
- /* The invocation failed and must be propagted */
- KMDTrace("Invoke", 2, "Invoke failed\n");
- /* Get rid of the old incoming request */
- FreeRequest((GenericReqPtr) req);
- fSSPtr->rPtr = (GenericPtr) NULL;
- FreeRequest((GenericReqPtr) callerSSP->invokePtr);
- callerSSP->invokePtr = (GenericPtr) NULL;
- fail(callerSSP);
- return;
- }
-
- case INVOKEUNAVAILABLE: {
- /* Make copies of vars since the request area will be freed */
- GODP theGODP = req->targetGODP;
- AbConPtr theAbConPtr = req->theAbConPtr;
-
- KMDTrace("Invoke", 2, "%s target object %s unavailable in %s\n",
- PPPOID(callerSSP->processOID), PPGOID(theGODP->ownOID),
- PPSSPlace(callerSSP));
- /* Get rid of the old incoming request */
- FreeRequest((GenericReqPtr) req);
- fSSPtr->rPtr = (GenericPtr) NULL;
- /* cf. req = callerSSP->invokePtr earlier */
- FreeRequest((GenericReqPtr) callerSSP->invokePtr);
- callerSSP->invokePtr = (GenericPtr) NULL;
- unavail(callerSSP, theGODP, theAbConPtr);
- return;
- }
-
-
- case INVOKEDONE: {
- KMDTrace("Invoke", 3, "%s Invocation Reply from own node in %s\n",
- PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
- /*
- * At this point, there is a return addr and parameters on the stack.
- * We need to simulate a return (including popping the arguments)
- * and to copy the results onto the stack.
- */
-
- /* Save return address */
- POPIT(callerSSP->regs.sp, invokeReq->returnAddr);
- if (invokeReq->i.argumentCount > 0) {
- /* pop arguments off of stack */
- callerSSP->regs.sp +=
- ((sizeof(AVariable) / sizeof(*callerSSP->regs.sp)) *
- invokeReq->i.argumentCount);
- }
-
- /* Now the sp points to the results, if any */
- if (invokeReq->i.resultCount > 0) {
- int resultSize;
- resultSize = invokeReq->i.resultCount * sizeof(AVariable);
- invokeReq->paramAddr = (AVariablePtr) callerSSP->regs.sp;
- KMDTrace("Invoke", 5,
- "result size %d, addr: 0x%06x to 0x%06x\n",
- resultSize, fSSPtr->regs.sp, invokeReq->paramAddr);
- /* Copy results to stack */
- bcopy((char *)fSSPtr->regs.sp, (char *)invokeReq->paramAddr,
- resultSize);
- }
-
-
- PUSHIT(callerSSP->regs.sp, invokeReq->returnAddr);
-
- /* Get rid of the old incoming request */
- FreeRequest((GenericReqPtr) req);
- fSSPtr->rPtr = (GenericPtr) NULL;
-
- schedule(callerSSP);
-
- return;
-
- }
-
- default: {
- assert(fResult != fResult); /* crash */
- abort();
- }
- }
- /* This point never reached */
- }
-
- LMStartMsg(&replyHandle, KMSG_EmKernel, EMKM_InvokeReply,
- (NodeNum) mGetLocNodeNum(callerSSODP->ownLoc));
- replyItem.hdr.itemTag = ReplyITag;
- replyItem.hdr.size = sizeof(replyItem);
- replyItem.callerSSOID = req->i.callerSSOID;
- replyItem.result = fResult;
- LMPutData(&replyHandle, &replyItem, sizeof(replyItem));
-
- /* Initialize sets */
- m = Map_Create();
- ar = Set_Create();
-
- if (fResult != INVOKEDONE) {
- /* It failed */
- KMDTrace("Invoke", 2, "%s %s\n", PPPOID(fSSPtr->processOID),
- fResult == INVOKEFAILED ? " invocation failed":
- " object unavailable");
- KMDTrace("Failure", 3, "%s %s\n", PPPOID(fSSPtr->processOID),
- fResult == INVOKEFAILED ? " invocation failed":
- " object unavailable");
- if (fSSPtr->regs.b->ownLoc > req->i.targetTryAtLoc) {
- /* The callee has an out of date forwarding address, so tell him
- about the new one. */
- AddToTTable(&replyHandle, (ODP) fSSPtr->regs.b, m, ar);
- }
-
-
- /*
- * If any processes are to move then the set of activation records is
- * non-empty.
- */
-
- MoveARs(&replyHandle, m, ar);
-
- cINVK_RemoteNoSuccessReturns++;
- LMSendMsg(&replyHandle);
-
- KMDTrace("FixMe", 5, "Maybe the visitors set should be respected\n");
- if (NonNULL(req->visitorSet)) Set_Destroy(req->visitorSet);
-
- Set_Destroy(ar);
- Map_Destroy(m);
-
- FreeRequest((GenericReqPtr) req);
- fSSPtr->rPtr = (GenericPtr) NULL;
- return;
- }
-
- if (req->i.resultCount > 0) {
- /* Copy the results into reply msg */
- KMDTrace("Invoke", 4, "%d result%s, returnByMoveMask 0x%08x\n",
- req->i.resultCount, mPLURAL(req->i.resultCount),
- req->returnByMoveMask);
- paramSize = req->i.resultCount * sizeof(AVariable);
- paramAddr = (AVariablePtr) fSSPtr->regs.sp;
- myParamItem.hdr.itemTag = ParamTag;
- myParamItem.hdr.size = paramSize + sizeof(ItemHdr);
- LMPutData(&replyHandle, &myParamItem, sizeof(ItemHdr));
- LMPutData(&replyHandle, paramAddr, paramSize);
- if (req->returnByMoveMask == 0) {
- for (i = req->i.resultCount; i ; i--, paramAddr++) {
- KMDTrace("Invoke", 4, "Result #%d %s\n", i, PPVar(paramAddr));
- AddVarToTTable(&replyHandle, paramAddr, m, ar);
- }
- } else {
- int pos;
- for (i = req->i.resultCount; i ; i--, paramAddr++) {
- if ((req->returnByMoveMask >> (req->i.resultCount-i)) & 1) {
- KMDTrace("Invoke", 4, "Result #%d by move return %s\n", i,
- PPVar(paramAddr));
- pos = LMCurrentPosition(&replyHandle);
- cINVK_CallByResultMovesDone++;
- MoveVarToTTable(&replyHandle, paramAddr, m, ar);
- cINVK_CallByResultBytesSent +=
- LMCurrentPosition(&replyHandle) - pos;
- } else {
- KMDTrace("Invoke", 4, "Result #%d by ref %s\n", i,
- PPVar(paramAddr));
- AddVarToTTable(&replyHandle, paramAddr, m, ar);
- }
- }
- }
- }
-
- /* Return any visiting objects */
- if (NonNULL(req->visitorSet)) {
- int pos;
- KMDTrace("Move", 3, "There are %d visitors\n",
- Set_Count(req->visitorSet));
- Set_For(req->visitorSet, visitingOID)
- visitingGODP = (GODP) OTLookup(visitingOID);
- if (IsNULL(visitingGODP)) {
- KMDTrace("Move", 2, "Lost visitor OID %s\n",
- PPGOID(visitingOID));
- continue;
- }
- if (!visitingGODP->tag.isResident) {
- KMDTrace("Move", 3, "Visitor has already left %s\n",
- PPGOID(visitingOID));
- continue;
- }
- KMDTrace("Move", 3, "Returning visitor OID %s\n",
- PPGOID(visitingOID));
- cINVK_CallByVisitReturnsDone++;
- pos = LMCurrentPosition(&replyHandle);
- MoveToTTable(&replyHandle, (ODP) visitingGODP, m, ar);
- cINVK_CallByVisitReturnBytesSent +=
- (LMCurrentPosition(&replyHandle) - pos);
- Set_Next;
- Set_Destroy(req->visitorSet);
- }
-
- if (fSSPtr->regs.b->ownLoc > req->i.targetTryAtLoc) {
- /* The callee has an out of date forwarding address, so tell him
- about the new one. */
- AddToTTable(&replyHandle, (ODP) fSSPtr->regs.b, m, ar);
- }
-
- /*
- * If any processes are to move then the set of activation records is
- * non-empty.
- */
-
- MoveARs(&replyHandle, m, ar);
-
- cINVK_RemoteReturns++;
- cINVK_RemoteReturnsBytesSent += LMCurrentPosition(&replyHandle);
- cINVK_RemoteReturnsPacketsSent += LMPacketPosition(&replyHandle);
-
- /*
- * Now actually send the message.
- */
-
- LMSendMsg(&replyHandle);
-
- /* Clean up */
- Map_Destroy(m);
- Set_Destroy(ar);
-
- FreeRequest((GenericReqPtr) req);
- fSSPtr->rPtr = (GenericPtr) NULL;
- return;
- }
-
- /************************************************************************/
- /* Invocation reply handling */
- /************************************************************************/
-
- HResult InvokeReplyHandler(fHandle)
- LMHandle fHandle;
- /* Handles incoming replies to previous invocation */
- {
- register SSPtr s;
- register SSODP theSSODP;
- register InvokeReqPtr req;
-
- InvokeReplyItem replyItem;
- ParamItem myParamItem;
- int length, resultSize;
-
- length = sizeof(replyItem);
- LMGetData(&fHandle, &replyItem, &length);
- assert(length == sizeof(replyItem));
-
- KMDTrace("Invoke", 4, "Invoke reply from %d\n", fHandle->mmMsgHdr.MsgSrc);
- theSSODP = (SSODP) OTLookup(replyItem.callerSSOID);
- assert (NonNULL(theSSODP));
- KMDTrace("FixMe", 3, "(Fix me: return SSODP cannot move!)\n");
- assert (mGetLocNodeNum(theSSODP->ownLoc) == GetLNN());
- s = theSSODP->dataPtr;
- KMDTrace("Invoke", 3, "%s Invocation Reply from LNN %d in %s\n",
- PPPOID(s->processOID), fHandle->mmMsgHdr.MsgSrc, PPSSPlace(s));
- req = (InvokeReqPtr) s->invokePtr;
- assert(NonNULL(req));
-
- switch (replyItem.result) {
-
- case INVOKEDONE: {
- break;
- }
-
- case INVOKEFAILED: {
- /* The invocation failed and the failure is propagating back here */
- KMDTrace("Invoke", 2, "Invoke failed\n");
- LMClose(&fHandle);
- FreeRequest((GenericReqPtr) s->invokePtr);
- s->invokePtr = (GenericPtr) NULL;
- fail(s);
- return;
- }
-
- case INVOKEUNAVAILABLE: {
- /* Make local copies since the request area will be freed */
- GODP theGODP = req->targetGODP;
- AbConPtr theAbConPtr = req->theAbConPtr;
-
- LMClose(&fHandle);
- KMDTrace("Invoke", 2, "%s target object %s unavailable in %s\n",
- PPPOID(s->processOID), PPGOID(theGODP->ownOID),
- PPSSPlace(s));
- /* cf. req = s->invokePtr earlier */
- FreeRequest((GenericReqPtr) s->invokePtr);
- s->invokePtr = (GenericPtr) NULL;
- unavail(s, theGODP, theAbConPtr);
- return;
- }
- }
-
- /*
- * At this point, there is a return addr and parameters on the stack.
- * We need to simulate a return (including popping the arguments)
- * and to copy the results onto the stack.
- */
-
- POPIT(s->regs.sp, req->returnAddr); /* save return address */
- if (req->i.argumentCount > 0) {
- /* pop arguments off of stack */
- s->regs.sp += ((sizeof(AVariable) / sizeof(*s->regs.sp)) *
- req->i.argumentCount);
- }
-
- /* Now the sp points to the results, if any */
- if (req->i.resultCount > 0) {
- length = sizeof(myParamItem);
- LMGetData(&fHandle, &myParamItem, &length);
- assert(length == sizeof(myParamItem));
- assert(myParamItem.hdr.itemTag == ParamTag);
- resultSize = myParamItem.hdr.size - length;
- assert(resultSize == req->i.resultCount * sizeof(AVariable));
- req->paramAddr = (AVariablePtr) s->regs.sp;
- KMDTrace("Invoke", 4, "result size %d, addr: 0x%05x\n",
- resultSize, req->paramAddr);
- /* Copy results to stack */
- length = resultSize;
- LMGetData(&fHandle, s->regs.sp, &length);
- KMDTrace("Invoke", 5, "Want result size %d, got %d\n", resultSize,
- length);
- assert(length == resultSize);
- }
-
- /* Create translation map */
- req->m = Map_Create();
- req->newSet = Set_Create();
- req->neededMap = Map_Create();
-
- /* Digest translation table information */
- DigestTable(&fHandle, req->m, req->neededMap, req->newSet, 0);
-
- LMClose(&fHandle);
-
- req->status = IRLoadingCode;
-
- if (Map_Count(req->neededMap) > 0) {
- Boolean didit;
- Map gotLoaded; /* Holds the ones loaded now */
- CodeODP newODP;
- OID theCTOID;
- ODP theOldODP;
-
- gotLoaded = Map_Create();
- /* Have to load some code */
-
- Map_For(req->neededMap, theCTOID, theOldODP)
- didit = LoadRequest(theCTOID, (GenericReqPtr) req);
- if (didit) Map_Insert(gotLoaded, (int) theCTOID, (int) theOldODP);
- Map_Next
-
- Map_For(gotLoaded, theCTOID, theOldODP)
- /* Delete it since no call back will occur */
- Map_Delete(req->neededMap, (int) theCTOID);
- newODP = (CodeODP) OTLookup(theCTOID);
- assert(NonNULL(newODP));
- Map_Insert(req->m, (int) theOldODP, (int) newODP->dataPtr);
- Map_Next
-
- Map_Destroy(gotLoaded);
-
- if (Map_Count(req->neededMap) > 0) return;
- }
- req->status = IRCodeLoadDone;
- InvokeReplyCallBack((GenericReqPtr) req, (OID) NULL);
- return;
- }
- /**********************************************************************/
- /* InvokeReplyCallBack */
- /**********************************************************************/
- HResult InvokeReplyCallBack(fReq, fOID)
- GenericReqPtr fReq;
- OID fOID;
- {
- InvokeReqPtr req = (InvokeReqPtr) fReq;
-
- KMDTrace("Invoke", 4, "InvokeReplyCallBack; OID %s status %s\n",
- PPOID(fOID),
- req->status == IRLocatingTarget ? "Locating Target" :
- req->status == IRWaitingForInvokeReply ? "Waiting for reply" :
- req->status == IRLoadingCode ? "Loading Code" :
- req->status == IRCodeLoadDone? "Code load done" :
- "BAD STATUS");
-
- switch (req->status) {
-
- case IRLoadingCode: {
- ODP oldODP;
- CodeODP newODP;
-
- /* Requested code has arrived */
- oldODP = (ODP) Map_Lookup(req->neededMap, (int) fOID);
- if (IsNIL(oldODP)) {
- ErrMsg("InvokeReplyCallBack %s -- ignored\n");
- return;
- }
- Map_Delete(req->neededMap, (int) fOID);
-
- newODP = (CodeODP) OTLookup(fOID);
- assert(NonNULL(newODP));
-
- /* (Note, m uses the pointer to the code area.) */
- Map_Insert(req->m, (int) oldODP, (int) newODP->dataPtr);
- KMDTrace("Invoke", 5, "%s loaded, (0x%04x -> 0x%04x)\n", PPCOID(fOID),
- oldODP, newODP->dataPtr);
-
- /* Check for completion of code loads */
- if (Map_Count(req->neededMap) == 0) {
- KMDTrace("Invoke", 3,
- "All needed code for invoke reply loaded\n");
- req->status = IRCodeLoadDone;
- InvokeHandlerCallBack((GenericReqPtr) req, (OID) NULL);
- }
- break;
- }
-
- case IRCodeLoadDone: {
- SSPtr s;
- register int i;
- register AVariablePtr
- p;
-
- s = req->requestor;
-
- /* All needed code has been loaded, now translate */
- DoTranslate(req->newSet, req->m, 0);
-
- if (req->i.resultCount > 0) {
- p = req->paramAddr;
- /* Translate results */
- for (i = req->i.resultCount; i; p++, i--) {
- if (p->myAbConPtr == (AbConPtr) EMNIL) {
- KMDTrace("Invoke", 4, "Result #%d is NIL\n", i);
- } else {
- p->myAbConPtr =
- (AbConPtr) Map_Lookup(req->m, (int) p->myAbConPtr);
- assert(p->myAbConPtr != (AbConPtr) EMNIL);
- KMDTrace("Invoke", 5, "new AbConPtr 0x%05x\n",
- p->myAbConPtr);
- if(p->myAbConPtr->tag.hasNoPointer) {
- KMDTrace("Invoke", 4,
- "Result #%d integer (or such) = %d (0x%04x), oldAbCon 0x%05x\n",
- i, p->myAddr, p->myAddr, p->myAbConPtr);
- } else if (p->myAddr == (DataAddr) EMNIL) {
- KMDTrace("Invoke", 4,
- "Result #%d is NIL (with non-NIL AbCon)\n", i,
- p->myAddr);
- } else {
- KMDTrace("Invoke", 5,
- "Result #%d OldODP 0x%05x old AbConPtr 0x%05x\n",
- i, p->myAddr, p->myAbConPtr);
- /* Translate ODP */
- p->myAddr =
- (DataAddr) Map_Lookup(req->m, (int) p->myAddr);
- assert(p->myAddr != (DataAddr) EMNIL);
- KMDTrace("Invoke", 5,
- "After translate: (0x%05x, 0x%05x)\n",
- p->myAbConPtr, p->myAddr);
- KMDTrace("Invoke", 4, "Result #%d Var %s\n", i,
- PPVar((AVariablePtr) p));
- }
- }
- }
- }
-
- PUSHIT(s->regs.sp, req->returnAddr);
-
- KMDTrace("Invoke", 3, "%s Invoke Reply from %s\n",
- PPPOID(s->processOID), PPGOID(req->i.targetOID));
-
- /* Clean up */
-
- Map_Destroy(req->m);
- Map_Destroy(req->neededMap);
- Set_Destroy(req->newSet);
-
- FreeRequest((GenericReqPtr) s->invokePtr);
- s->invokePtr = (GenericPtr) NULL;
-
- schedule(s);
-
- break;
- }
- default: {
- ErrMsg("Bad move status %d in InvokeReplyCallBack\n", req->status);
- abort();
- }
- }
- }
-
- /************************************************************************/
- /************************************************************************/
-
- HResult PingReqHandler(fMsg)
- EmMsgPtr fMsg;
- {
- PingReqItemPtr pingPtr;
- PongReqItemPtr pongPtr;
- EmMsgPtr replyPtr;
- int size = sizeof(MessageHeader) + sizeof(PingReqItem);
- KKStatus kstat;
-
- pingPtr = (PingReqItemPtr) &(fMsg->itemHdr);
-
- if (pingPtr->hdr.itemTag != PingITag) {
- DebugMsg(1, "PingReq: Bad item tag = %d\n", pingPtr->hdr.itemTag);
- MMDeallocateMsg((MessagePtr) fMsg);
- return;
- }
- DebugMsg(2, "PingReq from LNN %d, reqId %d replying ...\n",
- pingPtr->pingLNN, pingPtr->reqId);
- kstat = MMAllocateMsg(size, (MessagePtr *)&replyPtr);
- assert(mSUCCESS(kstat));
- pongPtr = (PongReqItemPtr) &(replyPtr->itemHdr);
- pongPtr->hdr.itemTag = PongITag;
- pongPtr->hdr.size = sizeof(PongReqItem);
- pongPtr->reqId = pingPtr->reqId;
- pongPtr->pongLNN = GetLNN();
- MMBuildMsg((MessagePtr)replyPtr, KMSG_EmKernel, EMKM_PongReq,
- pingPtr->pingLNN, (unsigned)size);
- kstat = MMSendMsg((MessagePtr) replyPtr);
- if ( !mSUCCESS(kstat) ) {
- DebugMsg(1, "Could not send pong msg, status 0x%05x\n", kstat);
- PutEdenMsg((int)kstat, (FILE *)NULL, (char **)0);
- }
- MMDeallocateMsg((MessagePtr) fMsg);
- MMDeallocateMsg((MessagePtr) replyPtr);
- }
-
-
- HResult PongReqHandler(fMsg)
- EmMsgPtr fMsg;
- {
- PongReqItemPtr pongPtr = (PongReqItemPtr) &fMsg->itemHdr;
-
- if (pongPtr->hdr.itemTag != PongITag) {
- DebugMsg(1, "PongReq: Bad item tag = %d\n", pongPtr->hdr.itemTag);
- MMDeallocateMsg((MessagePtr) fMsg);
- return;
- }
- DebugMsg(1, "PongReply recieved from LNN %d, reqId %d\n",
- pongPtr->pongLNN, pongPtr->reqId);
- MMDeallocateMsg((MessagePtr) fMsg);
- }
-
-
- void RIPing(fLNN)
- int fLNN;
- {
- register PingReqItemPtr pingPtr;
- EmMsgPtr pingMsg;
- int size = sizeof(MessageHeader)+sizeof(PingReqItem);
- KKStatus kstat;
-
- KMDPrint("RIPing, sending ping to LNN %d\n", fLNN);
- kstat = MMAllocateMsg(size, (MessagePtr *)&pingMsg);
- assert(mSUCCESS(kstat));
- pingPtr = (PingReqItemPtr) &pingMsg->itemHdr;
- pingPtr->hdr.itemTag = PingITag;
- pingPtr->hdr.size = sizeof(PingReqItem);
- pingPtr->reqId = nextPingId++;
- pingPtr->pingLNN = GetLNN();
- MMBuildMsg((MessagePtr)pingMsg, KMSG_EmKernel, EMKM_PingReq, fLNN,
- (unsigned)size);
- kstat = MMSendMsg((MessagePtr) pingMsg);
- if ( !mSUCCESS(kstat) ) {
- KMDPrint("Could not send ping msg, status 0x%05x\n", kstat);
- }
- MMDeallocateMsg((MessagePtr) pingMsg);
- KMDPrint("The pong reply will be printed on the kernel stdout\n");
- }
-
- /************************************************************************/
- /* LM Ping-pong message protocol: */
- /* Ping messages can be sent kernel-kernel at anytime. */
- /* The receiving kernel merely responds with a pong message. */
- /* Usefullness: For testing the connection between kernels. */
- /************************************************************************/
-
- HResult LMPingReqHandler();
- void LMPing();
-
- HResult LMPingReqHandler(fHandle)
- LMHandle fHandle;
- {
- LMHandle myHandle = fHandle;
- int length, i, sum;
-
- sum = 0;
- do {
- length = 4;
- LMGetData(&myHandle, &i, &length);
- if (length >0) {
- sum += length;
- printf(" %4d", i);
- if (i % 14 == 0) printf("\n");
- }
- } while (length > 0);
- printf("\nLong Msg total data length = %d\n", sum);
- LMClose(&myHandle);
- }
-
- void LMPing(fLNN)
- int fLNN;
- {
- LMHandle myHandle;
- int i;
- HOTSRecord *HOTSPtr;
-
- KMDPrint("LMPing, sending LMping to LNN %d, size = %d\n", fLNN,
- vLMPingDataSize);
- if (!mSUCCESS(HOTSSearchPtr(fLNN, &HOTSPtr)) ||
- ((HOTSPtr->NodeStat != Alive) && (HOTSPtr->NodeStat != Booting))
- ) {
- KMDPrint("Node %d not alive\n", fLNN);
- return;
- }
- LMStartMsg(&myHandle, KMSG_EmKernel, EMKM_LMPingReq, fLNN);
- for (i = 0; i < vLMPingDataSize; i += 4) {
- LMPutData(&myHandle, &i, 4);
- }
- LMSendMsg(&myHandle);
- KMDPrint("There will not be a reply.\n");
- }
-
- void LMSetPingDataSize(fInt)
- {
- KMDPrint("Changing PingDataSize to %d\n", fInt);
- vLMPingDataSize = fInt;
- }
-
- /**********************************************************************/
- /* Snapshot */
- void INVKInitiallyMap()
- {
- InitiallyReqPtr req;
- Map theMap;
- GODP theGODP;
- int dummy;
-
- Map_For(InitiallyMap, theGODP, theMap)
- KMDPrint("Initially map for 0x%05x (%s), %d entr%s\n", theGODP,
- PPGOID(theGODP->ownOID), Map_Count(theMap),
- mPLURALY(Map_Count(theMap)));
- Map_For(theMap, req, dummy);
- KMDPrint("%s in %s\n", PPPOID(req->theProcess->processOID),
- PPSSPlace(req->theProcess));
- Map_Next
- Map_Next
- }
-
- /**********************************************************************/
- /* Snapshot */
- void INVKFrozenMap()
- {
- IncomingIReqPtr req;
- Set reqSet;
- GODP theGODP;
- OID theOID;
-
- Map_For(FrozenMap, theOID, reqSet)
- theGODP = (GODP) OTLookup(theOID);
- KMDPrint("Initially map for 0x%05x (%s), %d entr%s\n", theGODP,
- PPGOID(theGODP->ownOID), Set_Count(reqSet),
- mPLURALY(Map_Count(reqSet)));
- Set_For(reqSet, req)
- KMDPrint("%s in %s\n", PPPOID(req->theProcess->processOID));
- Set_Next
- Map_Next
- }
-
- /**********************************************************************/
-
- void InvokeInit()
- {
- KMDTrace("Invoke", 5, "InvokeInit\n");
-
- MMDefineMsgHandler(KMSG_EmKernel, EMKM_InvokeReq,
- (HandlerPtr)InvokeHandler, (HandlerPtr *)NULL);
- MMDefineMsgHandler(KMSG_EmKernel, EMKM_InvokeReply,
- (HandlerPtr)InvokeReplyHandler, (HandlerPtr *)NULL);
- MMDefineMsgHandler(KMSG_EmKernel, EMKM_PingReq,
- (HandlerPtr) PingReqHandler, (HandlerPtr *)NULL);
- MMDefineMsgHandler(KMSG_EmKernel, EMKM_PongReq,
- (HandlerPtr)PongReqHandler, (HandlerPtr *)NULL);
- MMDefineMsgHandler(KMSG_EmKernel, EMKM_LMPingReq,
- (HandlerPtr)LMPingReqHandler, (HandlerPtr *)NULL);
-
- KMDSetSnap(RIPing); /* Define a snapshot to asynchronously send a ping */
- KMDSetSnap(LMPing); /* Define a snapshot to asynchronously send a ping */
- KMDSetSnap(LMSetPingDataSize);
- KMDSetVar(vLMPingDataSize);
- KMDSetTrace(Invoke);
-
- InitiallyMap = Map_Create();
- FrozenMap = Map_Create();
-
- KMDSetSnap(INVKInitiallyMap);
- KMDSetSnap(INVKFrozenMap);
- }
-
-